package com.wsoft.bpm.component;

import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Supplier;
import java.util.stream.Collectors;

/**
 * 异步轮询器
 *
 * @Author zhonglj
 * @Date 2025/2/27 14:23
 */
@Log4j2
@Component
public class AsyncTaskPoller {
    private final ExecutorService executor = Executors.newCachedThreadPool();

    /**
     * 周期性检查条件并执行任务（基于你的原始需求）
     *
     * @param conditionChecker 条件检查函数
     * @param timeout          总超时时间
     * @param checkInterval    检查间隔
     * @param onConditionMet   条件达成回调
     */
    public void executeWithCondition(Supplier<Boolean> conditionChecker, long timeout,
                                     long checkInterval, Runnable onConditionMet) {
        CompletableFuture.supplyAsync(() -> {
            long start = System.currentTimeMillis();
            while (System.currentTimeMillis() - start < timeout) {
                if (conditionChecker.get()) {
                    return true;
                }
                try {
                    Thread.sleep(checkInterval);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    break;
                }
            }
            return false;

        }, executor).handle((result, ex) -> {
            if (ex instanceof Exception) {
                log.error(ex.getMessage());

            } else if (result != null && result) {
                onConditionMet.run();

            }

            return null;
        });
    }

    /**
     * 合并多个异步任务结果
     *
     * @param tasks 任务列表
     * @return 合并后的结果Future
     */
    public <T> CompletableFuture<List<T>> combineTasks(List<Supplier<T>> tasks) {
        List<CompletableFuture<T>> futures = tasks.stream()
                .map(task -> CompletableFuture.supplyAsync(task, executor))
                .collect(Collectors.toList());
        return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
                .thenApply(v -> futures.stream()

                        .map(CompletableFuture::join)
                        .collect(Collectors.toList()));
    }

    /**
     * 关闭线程池
     */
    public void shutdown() {
        executor.shutdown();
    }
}
